using System;
namespace ComponentAce.Compression.Libs.zlib
{
	internal sealed class InfBlocks
	{
		private const int MANY = 1440;
		private const int Z_OK = 0;
		private const int Z_STREAM_END = 1;
		private const int Z_NEED_DICT = 2;
		private const int Z_ERRNO = -1;
		private const int Z_STREAM_ERROR = -2;
		private const int Z_DATA_ERROR = -3;
		private const int Z_MEM_ERROR = -4;
		private const int Z_BUF_ERROR = -5;
		private const int Z_VERSION_ERROR = -6;
		private const int TYPE = 0;
		private const int LENS = 1;
		private const int STORED = 2;
		private const int TABLE = 3;
		private const int BTREE = 4;
		private const int DTREE = 5;
		private const int CODES = 6;
		private const int DRY = 7;
		private const int DONE = 8;
		private const int BAD = 9;
		private static readonly int[] inflate_mask = new int[]
		{
			0,
			1,
			3,
			7,
			15,
			31,
			63,
			127,
			255,
			511,
			1023,
			2047,
			4095,
			8191,
			16383,
			32767,
			65535
		};
		internal static readonly int[] border = new int[]
		{
			16,
			17,
			18,
			0,
			8,
			7,
			9,
			6,
			10,
			5,
			11,
			4,
			12,
			3,
			13,
			2,
			14,
			1,
			15
		};
		internal int mode;
		internal int left;
		internal int table;
		internal int index;
		internal int[] blens;
		internal int[] int_0 = new int[1];
		internal int[] int_1 = new int[1];
		internal InfCodes codes;
		internal int last;
		internal int bitk;
		internal int bitb;
		internal int[] hufts;
		internal byte[] window;
		internal int int_2;
		internal int read;
		internal int write;
		internal object checkfn;
		internal long check;
		internal int dictionary
		{
			set
			{
				Array.Copy(byte_0, start, this.window, 0, value);
				this.write = value;
				this.read = value;
			}
		}
		internal InfBlocks(ZStream zstream_0, object checkfn, int int_3)
		{
			this.hufts = new int[4320];
			this.window = new byte[int_3];
			this.int_2 = int_3;
			this.checkfn = checkfn;
			this.mode = 0;
			this.reset(zstream_0, null);
		}
		internal void reset(ZStream zstream_0, long[] long_0)
		{
			if (long_0 != null)
			{
				long_0[0] = this.check;
			}
			if (this.mode == 4 || this.mode == 5)
			{
				this.blens = null;
			}
			if (this.mode == 6)
			{
				this.codes.free(zstream_0);
			}
			this.mode = 0;
			this.bitk = 0;
			this.bitb = 0;
			this.write = 0;
			this.read = 0;
			if (this.checkfn != null)
			{
				zstream_0.adler = (this.check = zstream_0._adler.adler32(0L, null, 0, 0));
			}
		}
		internal int proc(ZStream zstream_0, int int_3)
		{
			int num = zstream_0.next_in_index;
			int num2 = zstream_0.avail_in;
			int num3 = this.bitb;
			int i = this.bitk;
			int num4 = this.write;
			int num5 = (num4 < this.read) ? (this.read - num4 - 1) : (this.int_2 - num4);
			int num6;
			while (true)
			{
				switch (this.mode)
				{
				case 0:
					while (i < 3)
					{
						if (num2 == 0)
						{
							goto IL_8A0;
						}
						int_3 = 0;
						num2--;
						num3 |= (int)(zstream_0.next_in[num++] & 255) << i;
						i += 8;
					}
					num6 = (num3 & 7);
					this.last = (num6 & 1);
					switch (SupportClass.URShift(num6, 1))
					{
					case 0:
						num3 = SupportClass.URShift(num3, 3);
						i -= 3;
						num6 = (i & 7);
						num3 = SupportClass.URShift(num3, num6);
						i -= num6;
						this.mode = 1;
						continue;
					case 1:
					{
						int[] array = new int[1];
						int[] array2 = new int[1];
						int[][] array3 = new int[1][];
						int[][] array4 = new int[1][];
						InfTree.inflate_trees_fixed(array, array2, array3, array4, zstream_0);
						this.codes = new InfCodes(array[0], array2[0], array3[0], array4[0], zstream_0);
						num3 = SupportClass.URShift(num3, 3);
						i -= 3;
						this.mode = 6;
						continue;
					}
					case 2:
						num3 = SupportClass.URShift(num3, 3);
						i -= 3;
						this.mode = 3;
						continue;
					case 3:
						goto IL_839;
					default:
						continue;
					}
					break;
				case 1:
					while (i < 32)
					{
						if (num2 == 0)
						{
							goto IL_93E;
						}
						int_3 = 0;
						num2--;
						num3 |= (int)(zstream_0.next_in[num++] & 255) << i;
						i += 8;
					}
					if ((SupportClass.URShift(~num3, 16) & 65535) != (num3 & 65535))
					{
						goto Block_43;
					}
					this.left = (num3 & 65535);
					i = (num3 = 0);
					this.mode = ((this.left != 0) ? 2 : ((this.last != 0) ? 7 : 0));
					continue;
				case 2:
					if (num2 == 0)
					{
						goto IL_981;
					}
					if (num5 == 0)
					{
						if (num4 == this.int_2 && this.read != 0)
						{
							num4 = 0;
							num5 = ((0 < this.read) ? (this.read - num4 - 1) : (this.int_2 - num4));
						}
						if (num5 == 0)
						{
							this.write = num4;
							int_3 = this.inflate_flush(zstream_0, int_3);
							num4 = this.write;
							num5 = ((num4 < this.read) ? (this.read - num4 - 1) : (this.int_2 - num4));
							if (num4 == this.int_2 && this.read != 0)
							{
								num4 = 0;
								num5 = ((0 < this.read) ? (this.read - num4 - 1) : (this.int_2 - num4));
							}
							if (num5 == 0)
							{
								goto IL_9C4;
							}
						}
					}
					int_3 = 0;
					num6 = this.left;
					if (num6 > num2)
					{
						num6 = num2;
					}
					if (num6 > num5)
					{
						num6 = num5;
					}
					Array.Copy(zstream_0.next_in, num, this.window, num4, num6);
					num += num6;
					num2 -= num6;
					num4 += num6;
					num5 -= num6;
					if ((this.left -= num6) == 0)
					{
						this.mode = ((this.last != 0) ? 7 : 0);
						continue;
					}
					continue;
				case 3:
					while (i < 14)
					{
						if (num2 == 0)
						{
							goto IL_A62;
						}
						int_3 = 0;
						num2--;
						num3 |= (int)(zstream_0.next_in[num++] & 255) << i;
						i += 8;
					}
					num6 = (this.table = (num3 & 16383));
					if ((num6 & 31) <= 29 && (num6 >> 5 & 31) <= 29)
					{
						num6 = 258 + (num6 & 31) + (num6 >> 5 & 31);
						this.blens = new int[num6];
						num3 = SupportClass.URShift(num3, 14);
						i -= 14;
						this.index = 0;
						this.mode = 4;
						goto IL_3DC;
					}
					goto IL_A07;
				case 4:
					goto IL_3DC;
				case 5:
					goto IL_2AA;
				case 6:
					goto IL_4B;
				case 7:
					goto IL_C97;
				case 8:
					goto IL_D2B;
				case 9:
					goto IL_D71;
				}
				goto Block_49;
				while (true)
				{
					IL_2AA:
					num6 = this.table;
					if (this.index >= 258 + (num6 & 31) + (num6 >> 5 & 31))
					{
						break;
					}
					num6 = this.int_0[0];
					while (i < num6)
					{
						if (num2 == 0)
						{
							goto IL_BE8;
						}
						int_3 = 0;
						num2--;
						num3 |= (int)(zstream_0.next_in[num++] & 255) << i;
						i += 8;
					}
					num6 = this.hufts[(this.int_1[0] + (num3 & InfBlocks.inflate_mask[num6])) * 3 + 1];
					int num7 = this.hufts[(this.int_1[0] + (num3 & InfBlocks.inflate_mask[num6])) * 3 + 2];
					if (num7 < 16)
					{
						num3 = SupportClass.URShift(num3, num6);
						i -= num6;
						this.blens[this.index++] = num7;
					}
					else
					{
						int num8 = (num7 == 18) ? 7 : (num7 - 14);
						int num9 = (num7 == 18) ? 11 : 3;
						while (i < num6 + num8)
						{
							if (num2 == 0)
							{
								goto IL_BA5;
							}
							int_3 = 0;
							num2--;
							num3 |= (int)(zstream_0.next_in[num++] & 255) << i;
							i += 8;
						}
						num3 = SupportClass.URShift(num3, num6);
						i -= num6;
						num9 += (num3 & InfBlocks.inflate_mask[num8]);
						num3 = SupportClass.URShift(num3, num8);
						i -= num8;
						num8 = this.index;
						num6 = this.table;
						if (num8 + num9 > 258 + (num6 & 31) + (num6 >> 5 & 31) || (num7 == 16 && num8 < 1))
						{
							goto IL_B43;
						}
						num7 = ((num7 == 16) ? this.blens[num8 - 1] : 0);
						do
						{
							this.blens[num8++] = num7;
						}
						while (--num9 != 0);
						this.index = num8;
					}
				}
				this.int_1[0] = -1;
				int[] array5 = new int[1];
				int[] array6 = new int[1];
				int[] array7 = new int[1];
				int[] array8 = new int[1];
				array5[0] = 9;
				array6[0] = 6;
				num6 = this.table;
				num6 = InfTree.inflate_trees_dynamic(257 + (num6 & 31), 1 + (num6 >> 5 & 31), this.blens, array5, array6, array7, array8, this.hufts, zstream_0);
				if (num6 == 0)
				{
					this.codes = new InfCodes(array5[0], array6[0], this.hufts, array7[0], this.hufts, array8[0], zstream_0);
					this.blens = null;
					this.mode = 6;
					goto IL_4B;
				}
				goto IL_C2B;
				IL_3DC:
				while (this.index < 4 + SupportClass.URShift(this.table, 10))
				{
					while (i < 3)
					{
						if (num2 == 0)
						{
							goto IL_B00;
						}
						int_3 = 0;
						num2--;
						num3 |= (int)(zstream_0.next_in[num++] & 255) << i;
						i += 8;
					}
					this.blens[InfBlocks.border[this.index++]] = (num3 & 7);
					num3 = SupportClass.URShift(num3, 3);
					i -= 3;
				}
				while (this.index < 19)
				{
					this.blens[InfBlocks.border[this.index++]] = 0;
				}
				this.int_0[0] = 7;
				num6 = InfTree.inflate_trees_bits(this.blens, this.int_0, this.int_1, this.hufts, zstream_0);
				if (num6 == 0)
				{
					this.index = 0;
					this.mode = 5;
					goto IL_2AA;
				}
				goto IL_AA5;
				IL_4B:
				this.bitb = num3;
				this.bitk = i;
				zstream_0.avail_in = num2;
				zstream_0.total_in += (long)(num - zstream_0.next_in_index);
				zstream_0.next_in_index = num;
				this.write = num4;
				if ((int_3 = this.codes.proc(this, zstream_0, int_3)) != 1)
				{
					break;
				}
				int_3 = 0;
				this.codes.free(zstream_0);
				num = zstream_0.next_in_index;
				num2 = zstream_0.avail_in;
				num3 = this.bitb;
				i = this.bitk;
				num4 = this.write;
				num5 = ((num4 < this.read) ? (this.read - num4 - 1) : (this.int_2 - num4));
				if (this.last != 0)
				{
					goto IL_C90;
				}
				this.mode = 0;
			}
			return this.inflate_flush(zstream_0, int_3);
			Block_43:
			this.mode = 9;
			zstream_0.string_0 = "invalid stored block lengths";
			int_3 = -3;
			this.bitb = num3;
			this.bitk = i;
			zstream_0.avail_in = num2;
			zstream_0.total_in += (long)(num - zstream_0.next_in_index);
			zstream_0.next_in_index = num;
			this.write = num4;
			return this.inflate_flush(zstream_0, -3);
			Block_49:
			int_3 = -2;
			this.bitb = num3;
			this.bitk = i;
			zstream_0.avail_in = num2;
			zstream_0.total_in += (long)(num - zstream_0.next_in_index);
			zstream_0.next_in_index = num;
			this.write = num4;
			return this.inflate_flush(zstream_0, -2);
			IL_839:
			num3 = SupportClass.URShift(num3, 3);
			i -= 3;
			this.mode = 9;
			zstream_0.string_0 = "invalid block type";
			int_3 = -3;
			this.bitb = num3;
			this.bitk = i;
			zstream_0.avail_in = num2;
			zstream_0.total_in += (long)(num - zstream_0.next_in_index);
			zstream_0.next_in_index = num;
			this.write = num4;
			return this.inflate_flush(zstream_0, -3);
			IL_8A0:
			this.bitb = num3;
			this.bitk = i;
			zstream_0.avail_in = num2;
			zstream_0.total_in += (long)(num - zstream_0.next_in_index);
			zstream_0.next_in_index = num;
			this.write = num4;
			return this.inflate_flush(zstream_0, int_3);
			IL_93E:
			this.bitb = num3;
			this.bitk = i;
			zstream_0.avail_in = num2;
			zstream_0.total_in += (long)(num - zstream_0.next_in_index);
			zstream_0.next_in_index = num;
			this.write = num4;
			return this.inflate_flush(zstream_0, int_3);
			IL_981:
			this.bitb = num3;
			this.bitk = i;
			zstream_0.avail_in = num2;
			zstream_0.total_in += (long)(num - zstream_0.next_in_index);
			zstream_0.next_in_index = num;
			this.write = num4;
			return this.inflate_flush(zstream_0, int_3);
			IL_9C4:
			this.bitb = num3;
			this.bitk = i;
			zstream_0.avail_in = num2;
			zstream_0.total_in += (long)(num - zstream_0.next_in_index);
			zstream_0.next_in_index = num;
			this.write = num4;
			return this.inflate_flush(zstream_0, int_3);
			IL_A07:
			this.mode = 9;
			zstream_0.string_0 = "too many length or distance symbols";
			int_3 = -3;
			this.bitb = num3;
			this.bitk = i;
			zstream_0.avail_in = num2;
			zstream_0.total_in += (long)(num - zstream_0.next_in_index);
			zstream_0.next_in_index = num;
			this.write = num4;
			return this.inflate_flush(zstream_0, -3);
			IL_A62:
			this.bitb = num3;
			this.bitk = i;
			zstream_0.avail_in = num2;
			zstream_0.total_in += (long)(num - zstream_0.next_in_index);
			zstream_0.next_in_index = num;
			this.write = num4;
			return this.inflate_flush(zstream_0, int_3);
			IL_AA5:
			int_3 = num6;
			if (int_3 == -3)
			{
				this.blens = null;
				this.mode = 9;
			}
			this.bitb = num3;
			this.bitk = i;
			zstream_0.avail_in = num2;
			zstream_0.total_in += (long)(num - zstream_0.next_in_index);
			zstream_0.next_in_index = num;
			this.write = num4;
			return this.inflate_flush(zstream_0, int_3);
			IL_B00:
			this.bitb = num3;
			this.bitk = i;
			zstream_0.avail_in = num2;
			zstream_0.total_in += (long)(num - zstream_0.next_in_index);
			zstream_0.next_in_index = num;
			this.write = num4;
			return this.inflate_flush(zstream_0, int_3);
			IL_B43:
			this.blens = null;
			this.mode = 9;
			zstream_0.string_0 = "invalid bit length repeat";
			int_3 = -3;
			this.bitb = num3;
			this.bitk = i;
			zstream_0.avail_in = num2;
			zstream_0.total_in += (long)(num - zstream_0.next_in_index);
			zstream_0.next_in_index = num;
			this.write = num4;
			return this.inflate_flush(zstream_0, -3);
			IL_BA5:
			this.bitb = num3;
			this.bitk = i;
			zstream_0.avail_in = num2;
			zstream_0.total_in += (long)(num - zstream_0.next_in_index);
			zstream_0.next_in_index = num;
			this.write = num4;
			return this.inflate_flush(zstream_0, int_3);
			IL_BE8:
			this.bitb = num3;
			this.bitk = i;
			zstream_0.avail_in = num2;
			zstream_0.total_in += (long)(num - zstream_0.next_in_index);
			zstream_0.next_in_index = num;
			this.write = num4;
			return this.inflate_flush(zstream_0, int_3);
			IL_C2B:
			if (num6 == -3)
			{
				this.blens = null;
				this.mode = 9;
			}
			int_3 = num6;
			this.bitb = num3;
			this.bitk = i;
			zstream_0.avail_in = num2;
			zstream_0.total_in += (long)(num - zstream_0.next_in_index);
			zstream_0.next_in_index = num;
			this.write = num4;
			return this.inflate_flush(zstream_0, int_3);
			IL_C90:
			this.mode = 7;
			IL_C97:
			this.write = num4;
			int_3 = this.inflate_flush(zstream_0, int_3);
			num4 = this.write;
			int arg_CD1_0 = (num4 < this.read) ? (this.read - num4 - 1) : (this.int_2 - num4);
			if (this.read != this.write)
			{
				this.bitb = num3;
				this.bitk = i;
				zstream_0.avail_in = num2;
				zstream_0.total_in += (long)(num - zstream_0.next_in_index);
				zstream_0.next_in_index = num;
				this.write = num4;
				return this.inflate_flush(zstream_0, int_3);
			}
			this.mode = 8;
			IL_D2B:
			int_3 = 1;
			this.bitb = num3;
			this.bitk = i;
			zstream_0.avail_in = num2;
			zstream_0.total_in += (long)(num - zstream_0.next_in_index);
			zstream_0.next_in_index = num;
			this.write = num4;
			return this.inflate_flush(zstream_0, 1);
			IL_D71:
			int_3 = -3;
			this.bitb = num3;
			this.bitk = i;
			zstream_0.avail_in = num2;
			zstream_0.total_in += (long)(num - zstream_0.next_in_index);
			zstream_0.next_in_index = num;
			this.write = num4;
			return this.inflate_flush(zstream_0, -3);
		}
		internal void free(ZStream zstream_0)
		{
			this.reset(zstream_0, null);
			this.window = null;
			this.hufts = null;
		}
		internal int sync_point()
		{
			if (this.mode != 1)
			{
				return 0;
			}
			return 1;
		}
		internal int inflate_flush(ZStream zstream_0, int int_3)
		{
			int num = zstream_0.next_out_index;
			int num2 = this.read;
			int num3 = ((num2 <= this.write) ? this.write : this.int_2) - num2;
			if (num3 > zstream_0.avail_out)
			{
				num3 = zstream_0.avail_out;
			}
			if (num3 != 0 && int_3 == -5)
			{
				int_3 = 0;
			}
			zstream_0.avail_out -= num3;
			zstream_0.total_out += (long)num3;
			if (this.checkfn != null)
			{
				zstream_0.adler = (this.check = zstream_0._adler.adler32(this.check, this.window, num2, num3));
			}
			Array.Copy(this.window, num2, zstream_0.next_out, num, num3);
			num += num3;
			num2 += num3;
			if (num2 == this.int_2)
			{
				num2 = 0;
				if (this.write == this.int_2)
				{
					this.write = 0;
				}
				num3 = this.write - num2;
				if (num3 > zstream_0.avail_out)
				{
					num3 = zstream_0.avail_out;
				}
				if (num3 != 0 && int_3 == -5)
				{
					int_3 = 0;
				}
				zstream_0.avail_out -= num3;
				zstream_0.total_out += (long)num3;
				if (this.checkfn != null)
				{
					zstream_0.adler = (this.check = zstream_0._adler.adler32(this.check, this.window, num2, num3));
				}
				Array.Copy(this.window, num2, zstream_0.next_out, num, num3);
				num += num3;
				num2 += num3;
			}
			zstream_0.next_out_index = num;
			this.read = num2;
			return int_3;
		}
	}
}
